SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / examples / demonstrations / Chaotic Patterns.scd
blobdae29ecb045b9978849c60ee5619241d7c3c4951
1 // From SC2 distro
3 // Chaotic Patterns, version 0.1
4 // Some short examples showing how to create music (?) from 
5 // chaotic iterated maps and (integrated) ODE's. Most of this 
6 // is probably old news, but there are some new maps like Tinkerbell
7 // and Ikeda that are interesting. Most interesting is the ease of doing 
8 // this in SC2 ! Try them several times
9 // Staffan Liljegren, 991002, staffan@medialab.ericsson.se
12 // ======================= Discrete Maps ===================================
13 // Logistics map with fixed r = 3.9 
15 p = Prout({ 
16         var x;
17         x=0.5.rand;
18         loop({
19                 // xnew = r * xold * (1.0 - xold)
20                 x = 3.9 * x * (1.0 - x); 
21                 x.yield;}); });
22 // p returns points in 0<x<1 and in b we scale it to degrees from 0 - 7. You
23 // can try freq values instead, by using \freq instead of \degree 
24 b = Pbind(\dur, 0.1,\degree, p*7);
26 b.play;
30 // Logistics map with r = 3.687 and independent streams scaled to two octave 
31 // frygian scale, amp, legato and pan values)
34 p = Prout({ 
35         var x;
36         x=1.0.rand;
37         60.do({
38                 x = 3.687 * x * (1.0 - x); x.yield;}); });
39 b = Pbind(\scale, [0,1,3,5,7,8,10],\amp,p/4,\legato, p/2, \pan, p*2-1,\dur, 0.125, \degree, p*14);
41 Paddp(\mtranspose, Pseq([0,-2, 2],1),Ppar([Pbindf(b, \stretch, 2.0, \octave, 3),b++b])).play;
45 // Logistics map with changing r values 
46 // (3.4<r<4.0, with "chaos" entering at 3.57)
49 p = Prout({ var r, x;
50                 // Initial value
51                 x=0.5.rand;
52                  //     32-cycle, chaos?, ghost of 3-cycle in chaos,  chaos!
53                  //r = [3.569,    3.687,  3.8282,                     3.9].choose;
54                  r = rrand(3.4,4.0);
56                  // Uncomment this if you want to see the current r value
57                  //("// "++ r).postln;
58                  60.do({x = r * x * (1.0 - x); x.yield;}); });
59 // scale p to a pentatonic scale
60 b = Pbind(\scale, [0,3,5,7,9], \legato, p/2,\dur, Pseq([Pshuf([0.1,0.2,0.1],4)],5), \degree, p*12);
62 Pseq([Ppar([Pset(\octave,3,b),Pset(\octave,4,b)])], inf).play;
68 // Tinkerbell map / attractor scaled to 3 octave lydian
69 // Good for Glass/Reich/Nyman stuff...or ?
71 // I don't know any good initial conditions, but 0<x0,y0<0.3 seems to work, but
72 // it escapes to infinity on some occasions. I'll try to fix this
74 // p plays 40 notes with one randomly chosen c1 value                    
75 p = Prout({ 
76                 var x0, y0, c1, c2= -0.6013, c3=2.0, c4=0.4, x, y;
77                 //vary -0.7<c1<0.9. c1=0.3 is a limit cycle, c1=0.485 is a 7-period, c1=0.9 is chaotic
78                 c1 = rrand(-0.7,0.9);
79                 x0=0.2.rand; y0=0.2.rand; 
80                 // Uncomment this if you want to see the current c1 value
81                 //("// "++ c1).postln;
82                 40.do({
83                         x = x0.squared - y0.squared + (c1*x0) + (c2*y0); 
84                         y = (2*x0*y0) + (c3*x0) + (c4*y0);
85                         x0=x; y0=y;
86                         // I only use the y value, but feel free to experiment with (tiny) x values
87                         (y*21).yield;}); });
88 b = Pbind(\scale, [0,2,4,6,7,9,11], \legato, 0.2,\dur,0.1,\degree, p );
90 Paddp(\mtranspose, Pshuf([0,-3,-1, 3],2),Pseq([Ppar([b,b])], 2)).play;
94 // Ikeda map / attractor scaled to 2 octave aeolian
97 // p plays 40 notes with one randomly chosen c2 value                    
98 p = Prout({ var c2; 
99                 var x0, y0, c1=0.4, c3=6.0, rho=1.0, tao, x, y;
100                 //vary 0.0<c2<1.0. c2=0.726 is a 3-period, c2=0.780 is "crisis" c2=0.9 is chaotic
101                 c2 = rrand(0.3,0.9);
102                 x0=0.2.rand; y0=0.2.rand;
103                 // Uncomment this if you want to see the current c2 value
104                 //("// "++ c2).postln;
105                 40.do({
106                         tao = c1 - (c3/(1 + x0.squared + y0.squared));
107                         x = (c2 * ( (x0*cos(tao)) - (y0*sin(tao)) )) + rho;
108                         y = (c2 * ( (x0*sin(tao)) + (y0*cos(tao)) ));
109                         x0=x; y0=y;
110                         [x.abs/5+0.1,y*14].yield;}); });
111 b = Pbind(\scale, [0,2,3,5,7,8,10],\dur,0.1,[\legato,\degree], p );
113 Pseq([b],inf).play;
116 // Henon map / attractor (returns points in -1.5<x<1.5, -0.4<y<0.4, which are then
117 // used for pan (x values) and degrees from 2 octave dorian (y values)
119 p = Prout({ 
120         var x0, y0, x, y;
121         x0=0; y0=0;
122         loop({
123                 x = y0 + 1 - (1.4*x0*x0); 
124                 y = 0.3*x0; 
125                 x0=x;y0=y;
126                 [x, y*14].yield;}); });
127 b = Pbind(\scale, [0,2,3,5,7,9,10], \dur,0.125,[\pan, \degree], p );
129 Ptpar([0.0,Pbindf(b, \octave, 4,\stretch, 3.0), 4.0,b]).play;
133 // ==================== Continous Flows in next version =================================
135 // Non-working Lorentz attractor (Euler approximated)
137 p = Prout({ 
138         var x0,y0,z0,t,x,y,z;
139         t=0.01;
140         x0=2.0; y0=3.0; z0=5.0;
141         loop({ 
142                 x = x0 + (t*10*(y0-x0)); 
143                 y = y0 + (t*((x0*(28-z0))-y0)); 
144                 z = z0 + (t*((x0*y0)-(8*z0/3))); 
145                 x0=x; y0=y;z0=z;
146                 [x,y/10,z].postln.yield;}); });
147 b = Pbind([\pan,\dur,\degree], p);
149 b.play;
152 // To Come:
153 // Roessler attractor. See Rossler.ar for a chaotic noise implementation. 
154 // Duffing Oscillator